package handler

import (
	"api.video.com/api/internal/logic"
	"api.video.com/api/internal/svc"
	"api.video.com/api/internal/types"
	"errors"
	"fmt"
	"io"
	"net/http"
	"os"
	"strconv"

	"github.com/zeromicro/go-zero/rest/httpx"
)

func VideoChunkUploadHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		//获取文件信息
		file, body, err := r.FormFile("file")
		if err != nil {
			httpx.ErrorCtx(r.Context(), w, errors.New(`{"code":"201","msg":"文件接受失败"}`))
			return
		}
		//接收分片总数，当前分片数并且转换成int类型
		chunks := r.FormValue("chunks")
		currentChunk := r.FormValue("currentChunk")
		chunksInt, _ := strconv.Atoi(chunks)
		currentChunkInt, _ := strconv.Atoi(currentChunk)
		//重新生成文件名称
		newFileName := body.Filename + "_" + r.FormValue("userId") + "_" + r.FormValue("fileId") + "_" + r.FormValue("chunks") + "_" + r.FormValue("currentChunk")
		fmt.Println(newFileName)
		//打开文件
		_, err = os.Stat("./upload/temp/")
		if err != nil {
			os.MkdirAll("./upload/temp/", 0777)
		}
		f, err := os.Create("./upload/temp/" + newFileName)
		if err != nil {
			httpx.ErrorCtx(r.Context(), w, errors.New(`{"code":"201","msg":"生成文件"}`))
		}
		defer f.Close()
		io.Copy(f, file)
		//updFile, errs := os.OpenFile("./upload/temp/"+newFileName, os.O_CREATE|os.O_WRONLY, 0777)
		//if errs != nil {
		//	httpx.ErrorCtx(r.Context(), w, errors.New(`{"code":"10001","msg":"文件打开失败"}`))
		//	return
		//}
		//defer updFile.Close()
		//io.Copy(updFile, file)

		//判断上传文件是否结束
		if chunksInt == (currentChunkInt + 1) {
			//执行文件合并
			fmt.Println(444444444)
			merge(r.FormValue("fileName"), body.Filename, r.FormValue("userId"), r.FormValue("fileId"), r.FormValue("chunks"), r.FormValue("currentChunk"))
		}
		fmt.Println(3333333)
		r.Form.Set("file", "123")

		var req types.VideoChunkUploadRequest
		if err := httpx.Parse(r, &req); err != nil {
			httpx.ErrorCtx(r.Context(), w, err)
			return
		}

		l := logic.NewVideoChunkUploadLogic(r.Context(), svcCtx)
		resp, err := l.VideoChunkUpload(&req)
		if err != nil {
			httpx.ErrorCtx(r.Context(), w, err)
		} else {
			httpx.OkJsonCtx(r.Context(), w, resp)
		}
	}
}

// 处理分片封装函数
func merge(filename, chunkFilename, userId, fileId, chunks, currentChunk string) {
	fmt.Println(22222)
	currentChunkInt, _ := strconv.Atoi(currentChunk)
	// 指定分片文件的路径和顺序
	filePaths := []string{}
	for i := 0; i < currentChunkInt+1; i++ {
		iStr := strconv.Itoa(i)
		//分片
		newFileName := "./upload/temp/" + chunkFilename + "_" + userId + "_" + fileId + "_" + chunks + "_" + iStr
		filePaths = append(filePaths, newFileName)
	}
	_, err := os.Stat("./upload/upload/")
	if err != nil {
		os.MkdirAll("./upload/upload/", 0777)
	}
	newFile, err := os.Create("./upload/upload/" + filename)
	if err != nil {
		fmt.Println("无法创建合并后的文件：", err)
		return
	}
	defer newFile.Close()

	// 创建用于合并的新文件
	//newFilePath := "./upload/upload/" + filename
	//fmt.Println(1111)
	//fmt.Println(newFilePath)
	////创建新文件
	//newFile, err := os.Create(newFilePath)
	//if err != nil {
	//	fmt.Println("无法创建合并后的文件：", err)
	//	return
	//}
	//defer newFile.Close()

	for _, filePath := range filePaths {
		// 打开分片文件
		partFile, err := os.Open(filePath)
		fmt.Println(partFile)
		if err != nil {
			fmt.Println("无法打开分片文件：", filePath, err)
			return
		}
		defer partFile.Close()

		// 将分片文件的内容拷贝到合并后的文件
		_, err = io.Copy(newFile, partFile)
		if err != nil {
			fmt.Println("无法将分片文件内容拷贝到合并后的文件：", err)
			return
		}
	}

	fmt.Println("文件合并完成，合并后的文件位于：", "./upload/upload/"+filename)
}
